Глава
15
Обработка
ошибок
ColdFusion
обладает достаточным набором инструментов и методов, позволяющих отлаживать
и обрабатывать ситуации, которые приводят к ошибкам (исключительным ситуациям),
и благодаря этим инструментам и методам можно предотвращать возможные ошибки
и восстанавливать нормальную работу приложения после сбоев, которые в противном
случае были бы фатальными.
Следует отметить,
что главным инструментом при отладке CFML-страниц является непосредетвенно сам
редактор ColdFusion Studio, работа с которым была описана в предыдущих главах
книги. Впрочем, ColdFusion Server обладает некоторым набором инструментов,
позволяющих отслеживать значения переменных, анализировать результаты выполнения
запросов и отлаживать отдельные страницы.
Для отслеживания
значения переменных можно использовать тег <CFDUMP>, позволяющий наглядно
демонстрировать значения простых переменных, запросов, массивов, структур и
WDDX-переменных, созданных с помощью тега
<CFWDDX>.
Например,
для отладки структуры AttribMyTable достаточно добавить следующую строку:
<CFDUMP var
= #AttribMyTable#>
Для отладки
запроса (query) можно также использовать тег <CFDUMP>, позволяющий выводить
таблицу значений указанного запроса. Однако существует еще одна разновидность
отладки запроса. Это добавление атрибута DEBUG. Например:
<CFQUERY
NAME="GetTour" DATASOURCE="ttapplication.dsn#" DEBUG="Yes">
SELECT * FROM
Tour </CFQUERY>
В результате
внизу страницы будет выведена информация о количестве записей текущего запроса,
времени выполнения и самом запросе, как показано ниже:
GetTour
(Records=4, Time=10ms) SQL
= SELECT * FROM Tour
Для отладки
отдельного документа с возможностью просмотра сведений о времени выполнения
(execution time), параметрах URL (URL parameters) и переменных окружения CGI
(CGI variables) можно воспользоваться простым добавлением в конец строки URL
определения следующего параметра mode=debug. При этом вся строка URL для документа
MyPage.cfm может выглядеть так:
http://127.0.0.l/my-app/MyPage.cfm?mode=debug
Немаловажными
для отладки документа подобным образом, так же, как и для предыдущего примера
с добавлением к запросу атрибута DEBUG, являются настройки на странице администратора
"ColdFusion Administrator". По умолчанию возможность просмотра отладочной
информации предоставляется всем. Для ограничения же необходимо определить IP-адреса
компьютеров, имеющих право для просмотра отладочной информации, используя при
этом раздел страницы администратора Server | Debug Settings | Debugging IPs
(Сервер | Параметры отладки | IP-адреса для отлаки), как показано на рис.
15.1.
Также можно
настроить получаемую информацию, воспользовавшись разделом Server | Debug
Settings | Debug Options (Сервер | Параметры отладки | Настройка отладки)
все той же страницы администратора.
Рис.
15.1. Страница "ColdFusion Administrator", раздел Debugging
IPs
Методы, позволяющие
обрабатывать ошибки, можно разделить на две категории:
<CFTRY>/<CFCATCH>,
<CFTHROW>, <CFRETHROW>.
Синтаксис:
<CFERROR
TYPE = "Validation | Request | Monitor | Exception" TEMPLATE = "template_path"
MAILTO = "email address" EXCEPTION = "exception_type">
В табл. 15.1
приведено описание атрибутов тега <CFERROR>.
Таблица
15.1. Описание атрибутов тега <CFERROR>
Атрибут |
Описание |
||
TYPE TEMPLATE MAILTO
EXCEPTION |
Тип ошибки.
Обязательный атрибут. Возможные значения:
Относительный
путь к пользовательскому шаблону ошибок. Обязательный атрибут Электронный
адрес, по которому следует уведомлять о происходящих ошибках. Необязательный
атрибут Исключение.
Обязательный атрибут при использовании таких типов ошибок, как Monitor
и Exception |
||
Тип исключительной
ситуации может быть учтен как при использовании атрибута EXCEPTION тега <CFERROR>,
так и в сочетании с атрибутом TYPE тега <CFCATCH>, предназначенным для
формирования конструкций обработки исключительных ситуаций, непосредственно
на страницах приложения. Основные исключительные ситуации ColdFusion представлены
в табл. 15.2.
Таблица
15.2. Типы исключительных ситуаций
Тип |
Описание |
||
Database
Template |
Фиксирует неудачные
действия с базами данных и проблемы, связанные с ODBC Обнаруживает
ошибки в работе с шаблонами. Подобные исключения могут генерироваться
при использовании тегов <CFINCLUDE>,
<CFMODULE> И <CFERROR> |
||
Тип |
Описание |
||
Missinglnclude |
Обнаруживает
ошибки, где встречаются ссылки на несуществующие файлы |
||
Object |
Обнаруживает
ошибки в программном коде ColdFusion, который предусматривает работу
с объектами |
||
Security |
Фиксирует ошибки
в программном коде ColdFusion, который предусматривает обеспечение
безопасности |
||
Expression |
Обнаруживает
ошибки при неправильном использовании выражений |
||
Lock |
Фиксирует ошибки
при неудачной блокировке или во время выполнения блокировок, организованных
с помощью тега <CFLOCK> |
||
Application |
Обнаруживает
ошибки приложения, вызываемые тегом <CFTHROW> |
||
Any |
ч Обнаруживает
любые ошибки, которые не определены другими исключениями, в том числе
неожиданные внутренние ошибки |
||
Custom exception
type |
Обнаруживает
пользовательские ошибки, вызываемые тегом <CFTHROW> |
||
Создание
собственных шаблонов сообщений об ошибках
Для обнаружения
большинства ошибок ColdFusion Server использует стандартную страницу. Впрочем,
определяя собственные шаблоны в конфигурационном файле приложения Application.cfm,
вы можете управлять выводимой информацией при возникновении ошибок различного
характера. Причем ColdFusion позволяет определять шаблоны для различных типов
исключительных ситуаций и обращаться с разными типами исключений различными
способами.
Предположим,
нам необходимо выводить сообщения об ошибках двух видов для ситуаций при некорректном
заполнении форм (Validation) и для любых других ошибочных ситуаций, которые
иначе не обрабатываются (Request). Решением данной задачи может быть следующий
код, помещенный в конфигурационный файл Application.cfm приложения:
<CFERROR
TYPE="Validation"
TEMPLATE="ErrorsTemplatel.cfm"
MAILTO="Administrator@ipr.ru">
<CFERROR
TYPE="Request"
TEMPKATE="ErrorsTemplate2.cfm"
MAILTO="WebMaster@ipr.ru">
Здесь ErrorsTemplatel.cfm и ErrorsTemplate2.cfm являются шаблонами, определяющими содержание сообщений при возникновении исключительных ситуаций.
Для формирования
непосредственно самих шаблонов сообщения об ошибках ColdFusion предоставляет
целый набор встроенных переменных, определяющих ошибки. Причем в зависимости
от типа ошибки могут быть активизированы разные переменные. Например, для типа
ошибок validation поместим в наш шаблон ErrorsTemplatesl.cfm следующие переменные:
А для типа
ошибок Request поместим в шаблон ErrorsTemplates2.cfm такие встроенные переменные:
Также можно использовать следующие встроенные переменные ошибок:
Далее продемонстрируем
полный код страниц ErrorsTemplatel.cfm (листинг 15.1) и ErrorsTemplate2.cfm
(листинг 15.2), позволяющих выводить сообщения в момент возникновения различных
ошибок.
Листинг
15.1. Код страницы ErrorsTemplatel.cfm
<HTML>
<HEAD>
<link rel="STYLESHEET" type="text/css" href="Style.css">
<TITLE>ErrorsTemplatel</TITLE>
</HEAD> <BODY>
<hl>Errorl</hl>
<TABLE border="0">
<TR><TD bgcolor="Black" class="txtErr">ValidationHeader</TD></TR>
<TR><TD bgcolor="Silver">IError. ValidationHeader#</TD></TR>
<TR><TD bgcolor="Black" class="txtErr">InvalidFields</TD></TR>
<TR><TD bgcolor="Silver">tError.InvalidFieldst</TD></TR>
<TR><TD bgcolor="Black" class="txtErr">ValidationFooter</TD></TR>
<TR><TD bgcolor="Silver">#Error.ValidationFooter#</TD></TR>
</TABLE>
</BODY> </HTML>
Листинг
15.2. Код страницы ErrorsTemplate2.cfm
<HTML>
<HEAD>
<link rel="STYLESHEET"
type="text/css" href="Style.css">
<TITLE>ErrorsTemplate2</TITLE>
</HEAD>
<BODY>
<hl>Error2</hl>
<TABLE border="0">
<TR bgcolor="Black">
<TD class="txtErr">Template</td> <TD class="txtErr">DateTime</td>
</TR>
<TR bgcolor="Silver">
<TD>#Error.Template#</td> <TD>#Error.DateTime#</td> </TR>
<TR><TD
colspan="2" bgcolor="Black"
class="txtErr">Diagnostics</td></tr>
<TR><TD
colspan="2" bgcolor="Silver" class="txtErr2">
# Error. Diagnosticsl</TD></TR>
<TR><TD
colspan="2" bgcolor="Black"
class="txtErr">Browser</TDX/TR>
<TRXTD colspan="2" bgcolor="Silver">#Error.Browser#</TD></TR>
<TR bgcolor="Black">
<TD class="txtErr">RemoteAddress</td>
<TD class="txtErr">MailTo</td>
</TR>
<TR bgcolor="Silver">
<TD>#Error. RemoteAddress#</TD> <TD>#Error.MailTot</TD> </TR>
</TABLE>
</BODY> </HTML>
В дальнейшем
остается лишь проверить работу созданных нами шаблонов. Например, создадим форму
ввода, где при заполнении полей определенно будет сгенерирована ошибка с типом
validation:
<HTML>
<HEAD>
<TITLE>ErrorValidation</TITLE> </HEAD>
<BODY>
<FORM action="Action.cfm" method="Post">
<input type="Text" name="Field"><br>
<input type="Text"
name="Field integer">
<input type="Hidden"
name="Field_integer"
value="Error hidden field">
<input type="Submit" value="Send">
</FORM>
</BODY> </HTML>
Приведем
еще один пример, где в коде преднамеренно допустим ошибку типа Request, как
показано ниже:
<CFIF isDeeffined("MyVal")>
</CFIF>
Пользовательские
шаблоны сообщений об ошибках позволяют только обогатить Web-приложения собственными
стилизованными формами. Необходимо отметить, что ColdFusion Server автоматически
регистрирует ошибки в log-файлах в следующих случаях:
В других
случаях, при необходимости регистрировать ситуации, приводящие к ошибкам, необходимо
создавать пользовательский log-файл и формировать код, позволяющий производить
запись о возникающих ошибках.
Обработка
исключительных ситуаций
Одно из главных
преимуществ системы обработки исключительных ситуаций по сравнению с традиционными
методами обработки ошибок состоит в отделении процедуры обнаружения ошибки от
процедуры ее обработки. В ColdFusion для формирования конструкций обработки
исключительных ситуаций непосредственно на страницах приложения необходимо использовать
Теги <CFTRY>/<CFCATCH>.
<CFTRY>
Код с возможным
исключением
<CFCATCH
TYPE = "Exceptiontype">
Код обработки
исключительной ситуации
</CFCATCH>
Дополнительный
код для блока сfeatch </CFTRY>
Здесь атрибут
TYPE может принимать одно из значений типа исключительной ситуации, описанных
выше. Внутри же блока <CFTRY> содержится код, в ходе выполнения которого
могут возникать исключения или аварийное завершение программы, соответствующим
образом обрабатываемые посредством блока <CFCATCH> или путем переадресации
исключения с использованием тега <CFTHROW>.
Например:
<HTML>
<HEAD>
<TITLE>CFTRY
example1</TITLE> </HEAD> <BODY> <CFTRY>
<CF_NumFormat
Value = "10.123" Format = "__._">
<CFCATCH>
Error Message
</CFCATCH> </CFTRY> </BODY> </HTML>
Здесь в коде
программы между тегами <CFTRY> и <CFCATCH> преднамеренно допущена
ошибка, а в блок <CFCATCH> помещен код обработки исключительной
ситуации. В результате на экран будет выведено следующее сообщение сигнализирующее
об ошибке:
Error Message
Отметим,
что в приведенном примере блок <CFCATCH> использован без указания типа
исключительной ситуации, что подразумевает обработку любых ошибок. Причем внутри
блока <CFTRY> может следовать любое количество блоков <CFCATCH>.
При отсутствии же хотя бы одного блока <CFCATCH>, что вполне допустимо,
применение блока <CFTRY> бессмысленно.
Следующим
примером разделим обработку исключений для разных типов, в частности предусмотрим
исключение, фиксирующее неудачные действия по отношению к базам данных (Database),
при неправильном использовании выражений (Expression) и для остальных ошибок
(Anу):
<HTML>
<HEAD>
<TITLE>CFTRY example2</TITLE> </HEAD>
<BODY>
<CFTRY>
<CFQUERY
NAME="GetTour" DATASOURCE="#application.dsn#">
SELECT * FROM
Tour </CFQUERY>
<CF_NumFormat
Value = "10.123" Format = "__._e">
<CFCATCH
TYPE="Database">
<CFOUTPUT>Error Code: #Cfcatch.ErrorCode#</3FOUTPUT><br>
<CFOUTPUT>Detail: #Cfcatch.Detail#</CFOUTPUT> </CFCATCH>
<CFCATCH
TYPE="Expression">
Expression Error
</CFCATCH> <CFCATCH TYPE="Any">
Any Error </CFCATCH> </CFTRY>
</BODY>
</HTML>
Все исключения
обрабатываются последовательно в зависимости от расстановки блоков <CFCATCH>.
В нашем примере, если проблем с базой данных не будет, то программа перейдет
к обработке ошибок, возникших при использовании неправильных выражений. Если
и здесь проблем не будет, то следующим
шагом станут обрабатываться все остальные возможные исключения. Причем в нашем
случае при возникновении исключения с типом Database на экран будет выведен
код и детальная информация об ошибке, определяемые с помощью внутренних переменных
захвата Cf catch.
ErrorCode и Cf catch. Detail. Например, cледующий результат может указывать
на невозможность соединения с базой данных:
Error Code:
08001
Detail: [Sybase][ODBC Driver][Adaptive Server Anywhere]
Unable to connect to database server:
Database server
not running
Приложение
ColdFusion позволяет объявлять собственные исключительные ситуации и производить
переадресацию исключений с использованием тега <CFTHROW>.
Синтаксис:
<CFTHROW TYPE = "exception_type" MESSAGE V "message"
DETAIL = "detail_description"
ERRORCODE = "error_code"
EXTENDEDINFO = "additional_information">
В табл. 15.3
представлено описание атрибутов тега <CFTHROW>.
Таблица
15.3. Описание атрибутов тега <CFTHROW>
Атрибут |
Описание |
||
TYPE MESSAGE DETAIL ERRORCODE
EXTENDEDINFO |
Пользовательский
тип исключения. Необязательный атрибут. Если данный тип не определен,
то с помощью тега <CFCATCH> необходимо определить захват типа
Application или Any, куда будет перенаправлено данное исключение Сообщение, которое
описывает исключительную ситуацию. Необязательный атрибут Детальное описание
исключения. Необязательный атрибут Пользовательский код ошибки. Необязательный
атрибут Дополнительное описание исключения. Необязательный атрибут |
||
Например,
следующий код позволяет генерировать пользовательское исключение муЕхр по воскресеньям:
<HTML>
<HEAD>
<TITLE>CFTRY
example3</TITLE>
</HEAD>
<BODY> <CFTRY>
<CFSET NowDayWeek = DayOfWeek(Now () ) >
<CFIF Variables.NowDayWeek
eq 1>
<CFTHROW
TYPE="MyExp" ERRORCODE="1" EXTENDEDINFO="NotSundays"
DETAIL="Today
Sunday, that obliges you well to have a rest!" MESSAGE = "I
do not work on Sundays."> </CFIF> <CFCATCH TYPE="MyExp">
Message: <CFOUTPUT>ttCfcatch.Message#</CFOUTPUT> </CFCATCH>
<CFCATCH
TYPE="Any">
Any Error </CFCATCH> </CFTRY>
</BODY>
</HTML>
И если предположить,
что данный код выполнится в первый день недели, то на экран будет выведено сообщение
об ошибке с помощью внутренней переменной захвата Сfcatch.Message, как показано
ниже:
Message: I do
not work on Sundays.
Если вам
необходимо выполнить некоторые действия при возникновении исключения во внутреннем
блоке <CFTRY>, но не прекратить на этом обработку, а передать исключение
дальше, внешнему обработчику, вы можете воспользоваться тегом <CFRETHROW>,
позволяющим регенерировать исключение. Например:
<HTML>
<HEAD>
<TITLE>CFTRY
example4</TITLE> </HEAD> <BODY> <CFTRY>
<CFTRY>
<CF_NumFormat Value = "10.123" Format = "__-_e">
<CFCATCH
TYPE="Expression">
ErrNumber: <CFOUT.PUT>#Cfcatch. ErrNumber#</CFOOTPUT><br>
<CFRETHROW>
</CFCATCH>
</CFTRY>
<CFOUTPUT>MyCode</CFOUTPUT>
<CFCATCH TYPE="Any">
Type: <CFOUTPUT>#Cfcatch.Type#</CFOUTPUT> </CFCATCH> </CFTRY>
</BODY>
</HTML>
В результате
выполнения приведенного примера будет выведен номер ошибки и тип исключения,
.определяемые с помощью внутренних переменных захвата cfcatch.ErrNumber и cfcatch.Type,
как показано ниже:
ErrNumber: 16399
Type: EXPRESSION
Чтобы подвести
итог в описании исключительных ситуаций, приведем список внутренних переменных
захвата, часть из которых уже была использована в представленных примерах.
Внутренние
переменные захвата для большинства типов исключений: П Cf catch. Type — тип
исключения;
Переменные
захвата для исключения Database:
Переменная
захвата для исключения Expression: Cfcatch.ErrNumber — номер ошибки выражения.
Переменные
захвата для исключения Lock:
Cf catch.
MissingFileName — имя отсутствующего файла.
Подведем
итог. В данной главе вы познакомились с CFML-тегами <CFERROR>, <CFTRY>/<CFCATCH>,
<CFTHROW>, <CFRETHROW>.